Bug 1:defineModel 构建类型错误
问题描述
执行 pnpm build 时,TypeScript 编译器报错,提示 defineModel 的类型与预期不匹配。开发模式下一切正常,但构建阶段报错。
原因分析
这是 Vue 3.3 之后版本间的兼容性 bug。defineModel 是 Vue 3.3 引入的编译宏(Compiler Macro),在较早版本的 vue-tsc 中类型定义不完整。
解决方案
升级 Vue 核心依赖版本:
# 检查当前可升级的包
npx npm-check -u
# 重点关注以下两个包的版本
# vue: 升级到最新稳定版
# vue-tsc: 升级到最新稳定版
bash
升级完成后重新构建:
pnpm build
bash
构建应该正常通过,不再报 defineModel 的类型错误。
相关依赖版本对照
| 包名 | 问题版本 | 建议版本 |
|---|---|---|
vue | 3.3.x(早期) | 3.3.x+(最新补丁) |
vue-tsc | 1.6.x | 1.8.x+ |
@volar/vue-language-core | 旧版 | 与 vue-tsc 匹配 |
Bug 2:UnoCSS 动态图标不显示
问题描述
在首页 Card 组件中通过接口返回的动态 icon class 绑定到模板上,但图标始终不显示:
<!-- 动态绑定的 icon 不生效 -->
<div :class="project.icon" />
html
原因分析
UnoCSS(以及 Tailwind CSS)的工作原理是在构建阶段静态扫描源代码中的 class 名称,生成对应的 CSS 样式。动态绑定的 class 值在运行时才确定,构建工具无法提前识别,因此不会生成对应的 CSS 规则。
构建阶段扫描:
✅ class="i-mdi-vuejs" → 识别,生成 CSS
❌ :class="project.icon" → 无法识别,不生成 CSS
text
这是 UnoCSS 官方确认的设计限制。参考 GitHub Issue:"Using some dynamic value for icon not showing" -- 官方回复:dynamic values are not supported。
解决方案:safelist
在 uno.config.ts 中配置 safelist,强制 UnoCSS 预生成指定图标的 CSS:
// uno.config.ts
export default defineConfig({
// ...其他配置
safelist: [
// 从接口加载的动态图标
'i-mdi-vuejs',
'i-mdi-react',
'i-mdi-language-typescript',
'i-mdi-nodejs',
// ...按需添加更多图标
],
})
ts
safelist 的局限性
使用 safelist 意味着每次后端接口新增图标时,前端也需要同步更新配置文件。这是一个已知的取舍:
| 方案 | 优点 | 缺点 |
|---|---|---|
| safelist 预加载 | 简单直接,UnoCSS 原生支持 | 新增图标需改前端配置 |
| 全量导入图标集 | 无需维护列表 | 包体积显著增大 |
| 运行时动态渲染 | 真正的动态能力 | 需额外引入运行时方案 |
| 使用 Icon 组件 | 组件化方式灵活 | 需改造现有模板 |
其他动态 class 场景
safelist 不仅适用于图标,所有需要动态切换的 class 都需要同样处理:
<!-- 动态切换两个不同的图标 -->
<div :class="isActive ? 'i-mdi-check' : 'i-mdi-close'" />
<!-- 需要在 safelist 中添加 -->
safelist: ['i-mdi-check', 'i-mdi-close']
html
Bug 3:Mock 图片资源版本管理
问题描述
Mock 文件夹中存放了大量从慕课网爬取的图片资源(数百张,体积较大),这些文件不应该提交到 Git 仓库。
解决方案
在 .gitignore 中忽略 Mock 图片资源目录:
# Mock 图片资源(本地测试用)
mock/downloads/
mock/assets/
public/notes/**/downloads/
gitignore
这些资源仅用于本地开发测试,每位开发者自行在本地维护,不纳入版本控制。
最佳实践
| 类型 | 是否提交 | 说明 |
|---|---|---|
源代码(.ts, .vue) | 是 | 项目核心代码 |
Mock 数据(.json) | 视情况 | 小文件可提交,大文件忽略 |
Mock 图片(.png, .jpg) | 否 | 体积大,本地维护 |
| 爬虫脚本 | 视情况 | 工具脚本可提交 |
总结
| Bug | 根因 | 解决方案 |
|---|---|---|
defineModel 构建报错 | Vue 3.3 + vue-tsc 版本兼容性 | 升级 vue 和 vue-tsc 版本 |
| 动态图标不显示 | UnoCSS 不支持动态 class 扫描 | 配置 safelist 预加载 |
| Mock 图片资源体积过大 | 资源文件不应纳入版本控制 | .gitignore 忽略资源目录 |
↑